#include <sw/redis++/redis++.h>

void testGenericCommands(sw::redis::Redis& redis)
{
    printf("Generic 系列命令:\n");
    printf("=============================================\n");
    {
        printf("EXISTS 命令\n\n");
        redis.flushdb();

        bool b;
        b = redis.set("key1", "Hello");
        printf("redis < SET key1 \"Hello\"\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        long long e;
        e = redis.exists("key1");
        printf("redis < EXISTS key1\n");
        printf("redis > %lld\n", e);

        e = redis.exists("nosuchkey");
        printf("redis < EXISTS nosuckey\n");
        printf("redis > %lld\n", e);

        e = redis.set("key2", "World");
        printf("redis < SET key2 \"World\"\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        e = redis.exists({"key1", "key2", "nosuchkey"});
        printf("redis < EXISTS key1 key2 nosuckey\n");
        printf("redis > %lld\n", e);
        printf("=============================================\n");
    }
    {
        printf("DEL 命令\n\n");
        redis.flushdb();
        bool b;
        b = redis.set("key1", "Hello");
        printf("redis < SET key1 \"Hello\"\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        b = redis.set("key2", "World");
        printf("redis < SET key2 \"World\"\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        long long d;
        d = redis.del({"key1", "key2", "key3"});
        printf("redis < DEL key1 key2 key3\n");
        printf("redis > %lld\n", d);
        printf("=============================================\n");
    }
    {
        printf("KEYS 命令\n\n");
        redis.flushdb();
        std::unordered_map<std::string, std::string> kvs1 = {{"firstname", "Jack"}, {"lastname", "Stuntman"}, {"age", "35"}};
        redis.mset(kvs1.begin(), kvs1.end());
        printf("redis < MSET firstname Jack lastname Stuntman age 35\n");
        printf("redis > OK\n");

        std::vector<std::string> keys;
        std::insert_iterator<std::vector<std::string>> ins = std::inserter(keys, keys.begin());
        redis.keys("*name*", ins);
        printf("redis < KEYS *name*\n");
        int n = 1;
        for (std::vector<std::string>::iterator it = keys.begin(); it != keys.end(); ++it) {
            printf("redis > %d) %s\n", n++, it->c_str());
        }

        keys.clear();
        ins = std::inserter(keys, keys.begin());
        redis.keys("a??", ins);
        printf("redis < KEYS a??\n");
        n = 1;
        for (std::vector<std::string>::iterator it = keys.begin(); it != keys.end(); ++it) {
            printf("redis > %d) %s\n", n++, it->c_str());
        }
        
        keys.clear();
        ins = std::inserter(keys, keys.begin());
        redis.keys("*", ins);
        printf("redis < KEYS *\n");
        n = 1;
        for (std::vector<std::string>::iterator it = keys.begin(); it != keys.end(); ++it) {
            printf("redis > %d) %s\n", n++, it->c_str());
        }

        printf("=============================================\n");
    }
    {
        printf("EXPIRE 命令\n");
        printf("TTL 命令\n\n");
        redis.flushdb();
        bool b;
        b = redis.set("mykey", "Hello");
        printf("redis < SET mykey \"Hello\"\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        b = redis.expire("mykey", std::chrono::seconds(10));
        printf("redis < EXPIRE mykey 10\n");
        printf("redis > %d\n", b ? 1 : 0);

        long long ttl = redis.ttl("mykey");
        printf("redis < TTL mykey\n");
        printf("redis > %lld\n", ttl);


        printf("=============================================\n");
    }
    {
        printf("PTTL 命令\n\n");
        redis.flushdb();
        bool b;
        b = redis.set("mykey", "Hello");
        printf("redis < SET mykey \"Hello\"\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        b = redis.expire("mykey", std::chrono::seconds(10));
        printf("redis < EXPIRE mykey 10\n");
        printf("redis > %d\n", b ? 1 : 0);

        long long pttl = redis.pttl("mykey");
        printf("redis < TTL mykey\n");
        printf("redis > %lld\n", pttl);

        printf("=============================================\n");
    }
    {
        printf("TYPE 命令\n\n");
        redis.flushdb();
        bool b;
        b = redis.set("key1", "value");
        printf("redis < SET key1 \"value\"\n");
        printf("redis > %s\n", b ? "OK" : "(nil)");

        long long c = redis.lpush("key2", "value");
        printf("redis < LPUSH key2 \"value\"\n");
        printf("redis > %lld\n", c);

        c = redis.sadd("key3", "value");
        printf("redis < SADD key3 \"value\"\n");
        printf("redis > %lld\n", c);

        std::string type = redis.type("key1");
        printf("redis < TYPE key1\n");
        printf("redis > \"%s\"\n", type.c_str());

        type = redis.type("key2");
        printf("redis < TYPE key2\n");
        printf("redis > \"%s\"\n", type.c_str());

        type = redis.type("key3");
        printf("redis < TYPE key3\n");
        printf("redis > \"%s\"\n", type.c_str());

        printf("=============================================\n");
    }
}

int main()
{
    sw::redis::Redis redis("tcp://127.0.0.1:6379");

    // Generic commands
    testGenericCommands(redis);
    return 0;
}